package aso.fighting_groups;

import sim.engine.SimState;
import sim.engine.Steppable;
import sim.field.grid.DoubleGrid2D;

/**
 * This agent decreases evaporates and diffuses all the smell at each time step.
 * See the comments in Diffuser.java for a tutorial on how to speed up Java
 * many-fold in classes such as Diffuser.
 */

class FGDiffuser implements Steppable {
    /**
     * UID for serialization.
     */
    private static final long serialVersionUID = 1077809699835966066L;

    @Override
    public void step(final SimState state) {
        FightingGroups fg = (FightingGroups) state;

        // locals are faster than instance variables
        final DoubleGrid2D valgrid = fg.getSmellGrid();
        final double[][] valgridField = fg.getSmellGrid().field;
        final double[][] valgrid2Field = fg.getSmellGrid2().field;
        final int gridWidth = valgrid.getWidth();
        final int gridHeight = valgrid.getHeight();
        final double evaporationRate = fg.getEvaporationRate();
        final double diffusionRate = fg.getDiffusionRate();

        double average;

        double[] past = valgridField[valgrid.stx(-1)];
        double[] current = valgridField[0];
        double[] next;
        double[] put;

        int yminus1;
        int yplus1;

        // for each x and y position
        for (int x = 0; x < gridWidth; x++) {
            next = valgridField[valgrid.stx(x + 1)];
            put = valgrid2Field[valgrid.stx(x)];

            yminus1 = valgrid.sty(-1); // initialized
            for (int y = 0; y < gridHeight; y++) {
                // for each neighbor of that position
                // go across top
                yplus1 = valgrid.sty(y + 1);
                average = (past[yminus1] + past[y] + past[yplus1] + current[yminus1] + current[y] + current[yplus1] + next[yminus1] + next[y] + next[yplus1]) / 9.0;

                // load the new value into HeatBugs.this.valgrid2
                put[y] = evaporationRate * (current[y] + diffusionRate * (average - current[y]));

                // set y-1 to what y was "last time around"
                yminus1 = y;
            }

            // swap elements
            past = current;
            current = next;
        }

        // now finally copy HeatBugs.this.valgrid2 to HeatBugs.this.valgrid, and
        // we're done
        valgrid.setTo(fg.getSmellGrid2());
    }
}
